package com.weilive.core.utils;

public class MermerHash {
	
	public static int hash(final byte[] data) {
		return hash(data, 0, data.length, 0x9747b28c);
	}

	/**
	 * @param data byte array to hash
	 * @param offset offset of the array to hash
	 * @param length length of the array to hash
	 * @param seed initial seed value
	 * @return 32 bit hash of the given array
	 */
	public static int hash(final byte[] data, int offset, int length, int seed) {
		// 'm' and 'r' are mixing constants generated offline.
		// They're not really 'magic', they just happen to work well.
		final int m = 0x5bd1e995;
		final int r = 24;
		// Initialize the hash to a random value
		int h = seed ^ length;
		int length4 = length / 4;

		for (int i = 0; i < length4; i++) {
			final int i4 = i * 4 + offset;
			int k = (data[i4] & 0xff) + ((data[i4 + 1] & 0xff) << 8)
					+ ((data[i4 + 2] & 0xff) << 16)
					+ ((data[i4 + 3] & 0xff) << 24);
			k *= m;
			k ^= k >>> r;
			k *= m;
			h *= m;
			h ^= k;
		}

		// Handle the last few bytes of the input array
		final int last = (length & ~3) + offset;
		switch (length % 4) {
		case 3:
			h ^= (data[last + 2] & 0xff) << 16;
		case 2:
			h ^= (data[last + 1] & 0xff) << 8;
		case 1:
			h ^= (data[last] & 0xff);
			h *= m;
		}

		h ^= h >>> 13;
		h *= m;
		h ^= h >>> 15;

		return h;
	}

}
